package com.fingard.dsp.bank.directbank.pab02.Util.api.bean;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.fingard.dsp.bank.directbank.pab02.Util.api.exception.FtpErrCode;
import com.fingard.dsp.bank.directbank.pab02.Util.api.exception.FtpException;
import com.fingard.dsp.bank.directbank.pab02.Util.api.ftp.http.FtpConnector;

import java.io.InputStream;

/**
 * @date 2018年8月8日上午10:22:51
 * @description 客户端，文件下载类
 */
public class FtpGet {
	private final static Log log = LogFactory.getLog(FtpGet.class);

	private String remoteFileName = null;
	private String localFileName = null;
	private FtpConnector conn = null;
	private EsbFile file = null;
	private FileMsgBean bean = null;

	/**
	 * 进行用户口令及文件读取权限的认证
	 * 
	 * @return 文件FileMsgBean对象
	 */
	private FileMsgBean doAuth() throws FtpException {
		if (log.isInfoEnabled())
			log.info("开始进行认证.");
		bean.setFileMsgFlag(FileMsgType.GET_AUTH);
		// 发请求获取响应
		InputStream in = conn.sendRequest(conn.beanToBytes(bean));
		conn.readHead(bean, in);
		if (log.isInfoEnabled())
			log.info("用户认证结束.");
		close(false);
		return bean;
	}

	/**
	 * 构造函数，进行的处理包括：1、文件本地文件对象的创建；2、进行用户的认证处理
	 * 
	 * @param bean
	 *            消息bean
	 * @throws FtpException
	 */
	public FtpGet(FileMsgBean bean)
			throws FtpException {
		// 属性赋值
		remoteFileName = bean.getRemotePath();
		localFileName = bean.getLocalPath();

		// 创建下载的文件
		file = new EsbFile(localFileName, EsbFile.CLIENT);
		this.bean = bean;
		// 建立与服务器的连接
		conn = new FtpConnector(bean.getFileServerUrl());
		// 进行用户口令及文件读取权限的认证
		this.doAuth();
        //如果第一次返回的是其他错误码，抛出对应的异常
		if (!FileMsgType.GET_AUTH.equals(bean.getFileMsgFlag())) {
			throw new FtpException(bean.getFileMsgFlag());
		}
		if (bean.isAuthFlag()) {
			if (log.isInfoEnabled())
				log.info("用户认证成功!");
		} else {
			log.error("用户认证失败!");
			bean.setFileRetMsg(FtpErrCode.getCodeMsg(FtpErrCode.AuthUserFailed));
			throw new FtpException(FtpErrCode.AuthUserFailed);
		}
		if (bean.isAuthTokenFlag()) {
			if (log.isInfoEnabled())
				log.info("token认证成功!");
			file.openForWrite();
		} else {
			log.error("token认证失败!");
			bean.setFileRetMsg(FtpErrCode.getCodeMsg(FtpErrCode.AuthTokenFailed));
			throw new FtpException(FtpErrCode.AuthTokenFailed);
		}
	}

	/**
	 * 实现文件的下载处理
	 * 
	 * @return 下载标志 true - 成功 false - 失败
	 * @throws FtpException
	 */
	public boolean doGetFile() throws FtpException {
		try {
			if (log.isInfoEnabled())
				log.info("开始下载文件" + bean.getFileName());
			bean.setFileIndex(0);
			while (true) {
				// 设置要读取的分配，向服务器请求信息
				bean.setFileMsgFlag(FileMsgType.GET);
				bean.addFileIndex();

				InputStream in = conn.sendRequest(conn.beanToBytes(bean));
				// 读取文件的内容
				conn.readHead(bean, in);
				if (FileMsgType.SUCC.equals(bean.getFileMsgFlag())) {
					if (log.isDebugEnabled())
						log.debug("下载文件[" + bean.getFileName() + "]" + "第[" + bean.getFileIndex()
								+ "]分片成功");
				} else {
					throw new FtpException(bean.getFileMsgFlag());
				}
				// 读取文件内容写入到文件中
				conn.readCont(bean, in);
				file.write(bean);

				// 判断是否是最后一个分片，如果是最后一个分片，则退出
				if (bean.isLastPiece())
					break;
			}

			// 完成文件的写入处理，包括文件的MD5校验和文件的重命名
			file.finish(bean.getMd5());
			if (log.isInfoEnabled())
				log.info("文件下载结束");
			close(true);
			return true;
		} catch (Exception e) {
			if (e instanceof FtpException) {
				throw (FtpException) e;
			} else {
				if (log.isErrorEnabled()) {
					log.error("文件下载错误", e);
				}
				throw new FtpException(FtpErrCode.FileDownError);
			}
		} finally {
			close(true);
		}

	}

	/**
	 * 结束文件的下载处理，关闭连接对象和本地文件
	 * 
	 * @throws FtpException
	 */
	public void close(boolean closeFile) {

		if (file != null && closeFile)
			try {
				file.close();
			} catch (FtpException e) {

				if (log.isInfoEnabled())
					log.info("文件关闭异常:" + e);
			}
	}

}
